package com.unittec.drainage.provider.utils;

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.Bucket;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.ObjectMetadata;
import com.unittec.drainage.provider.ApplicationContextProvider;
import com.unittec.drainage.provider.log.Log;
import com.unittec.drainage.provider.service.RootCommonUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.env.Environment;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;

/**
 * @author wuxinwei
 */
public class OssAliYunUtils {

    private static String endpoint;

    private static String accessKeyId;

    private static String accessKeySecret;

    private static String bucketName;

    private static Log log;

    /**
     * 获取阿里云OSS客户端对象
     *
     * @return ossClient
     */
    public static OSSClient getOssClient() {

        Environment environment = ApplicationContextProvider.getApplicationContext().getBean(Environment.class);

        log = ApplicationContextProvider.getBean(Log.class);

        String endpointTemp = "";
        String accessKeyIdTemp = "";
        String accessKeySecretTemp = "";
        String bucketNameTemp = "";

        String profile = environment.getProperty("spring.profiles.active");
        log.sysInfoLog("getOssClient", "当前环境为：" + profile);
        if ("dev".equalsIgnoreCase(profile)) {
            endpointTemp = environment.getProperty("oss.aliyun.dev.endpoint");
            accessKeyIdTemp = environment.getProperty("oss.aliyun.dev.accessKeyId");
            accessKeySecretTemp = environment.getProperty("oss.aliyun.dev.accessKeySecret");
            bucketNameTemp = environment.getProperty("oss.aliyun.dev.bucketName");
        }
        if ("test".equalsIgnoreCase(profile)) {
            endpointTemp = environment.getProperty("oss.aliyun.test.endpoint");
            accessKeyIdTemp = environment.getProperty("oss.aliyun.test.accessKeyId");
            accessKeySecretTemp = environment.getProperty("oss.aliyun.test.accessKeySecret");
            bucketNameTemp = environment.getProperty("oss.aliyun.test.bucketName");
        }
        if ("pro".equalsIgnoreCase(profile)) {
            endpointTemp = environment.getProperty("oss.aliyun.pro.endpointPublic");
            accessKeyIdTemp = environment.getProperty("oss.aliyun.pro.accessKeyId");
            accessKeySecretTemp = environment.getProperty("oss.aliyun.pro.accessKeySecret");
            bucketNameTemp = environment.getProperty("oss.aliyun.pro.bucketName");
            if (StringUtils.isBlank(endpointTemp)) {
                endpointTemp = environment.getProperty("oss.aliyun.pro.endpointPublic");
            }
        }
        endpoint = endpointTemp;
        accessKeyId = accessKeyIdTemp;
        accessKeySecret = accessKeySecretTemp;
        bucketName = bucketNameTemp;
        log.sysInfoLog("getOssClient", "accessKeyId:" + accessKeyId + ",accessKeySecret:" + accessKeySecret
            + ",endpoint:" + endpoint + ",bucketName:" + bucketName);
        return new OSSClient(endpointTemp, accessKeyIdTemp, accessKeySecretTemp);
    }

    /**
     * 创建存储空间
     *
     * @param ossClient
     *            OSS连接
     * @param bucketName
     *            存储空间
     * @return
     */
    public static String createBucketName(OSSClient ossClient, String bucketName) {
        // 存储空间
        final String bucketNames = bucketName;
        if (!ossClient.doesBucketExist(bucketName)) {
            // 创建存储空间
            Bucket bucket = ossClient.createBucket(bucketName);
            return bucket.getName();
        }
        return bucketNames;
    }

    /**
     * 删除存储空间buckName
     *
     * @param ossClient
     *            oss对象
     * @param bucketName
     *            存储空间
     */
    public static void deleteBucket(OSSClient ossClient, String bucketName) {
        ossClient.deleteBucket(bucketName);
    }

    /**
     * 创建模拟文件夹
     *
     * @param ossClient
     *            oss连接
     * @param bucketName
     *            存储空间
     * @param folder
     *            模拟文件夹名如"qj_nanjing/"
     * @return 文件夹名
     */
    public static String createFolder(OSSClient ossClient, String bucketName, String folder) {
        // 文件夹名
        final String keySuffixWithSlash = folder;
        // 判断文件夹是否存在，不存在则创建
        if (!ossClient.doesObjectExist(bucketName, keySuffixWithSlash)) {
            // 创建文件夹
            ossClient.putObject(bucketName, keySuffixWithSlash, new ByteArrayInputStream(new byte[0]));
            // 得到文件夹名
            OSSObject object = ossClient.getObject(bucketName, keySuffixWithSlash);
            String fileDir = object.getKey();
            return fileDir;
        }
        return keySuffixWithSlash;
    }

    /**
     * 根据key删除OSS服务器上的文件
     *
     * @param ossClient
     *            oss连接
     * @param bucketName
     *            存储空间
     * @param folder
     *            模拟文件夹名 如"qj_nanjing/"
     * @param key
     *            Bucket下的文件的路径名+文件名 如："upload/cake.jpg"
     */
    public static void deleteFile(OSSClient ossClient, String bucketName, String folder, String key) {
        ossClient.deleteObject(bucketName, folder + key);
        ossClient.shutdown();
    }

    /**
     * 下载文件
     *
     * @param path
     * @param target
     * @throws IOException
     */
    public static void download(String path, File target) throws IOException {
        OSSClient ossClient = getOssClient();
        try {
            OSSObject object = ossClient.getObject(bucketName, path);
            if (!Files.exists(target.getParentFile().toPath())) {
                Files.createDirectories(target.getParentFile().toPath());
            }
            Files.copy(object.getResponse().getContent(), target.toPath(), StandardCopyOption.REPLACE_EXISTING);
        } finally {
            ossClient.shutdown();
        }
    }

    /**
     * 上传文件
     *
     * @param file
     * @param basePath
     * @param fileName
     * @return
     */
    public static String upload(File file, String basePath, String fileName) {
        OSSClient ossClient = null;
        try {
            ossClient = getOssClient();
            Calendar calendar = Calendar.getInstance();
            String path = basePath + "/" + calendar.get(Calendar.YEAR) + "/" + (calendar.get(Calendar.MONTH) + 1) + "/"
                + calendar.get(Calendar.DATE) + "/" + UUID.randomUUID().toString() + "/" + fileName;
            ossClient.putObject(bucketName, path, file);
            return path;
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

    /**
     * 异步上传文件到OSS
     *
     * @param path
     * @param fileName
     * @param is
     * @return
     */
    public static String uploadObject2OssAnsy(String path, String fileName, InputStream is) throws Exception {
        OSSClient ossClient = getOssClient();

        String url = null;
        try {

            if (ossClient.doesBucketExist(bucketName)) {
                // logger.error("您已经创建Bucket：" + bucketName + "。");
            } else {
                // 创建Bucket。
                ossClient.createBucket(bucketName);
            }

            // 创建上传Object的Metadata
            ObjectMetadata metadata = new ObjectMetadata();
            // 上传的文件的长度
            metadata.setContentLength(is.available());
            // 指定该Object被下载时的网页的缓存行为
            metadata.setCacheControl("no-cache");
            // 指定该Object下设置Header
            metadata.setHeader("Pragma", "no-cache");
            // 指定该Object被下载时的内容编码格式
            metadata.setContentEncoding("utf-8");
            // 文件的MIME，定义文件的类型及网页编码，决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成，
            // 如果没有扩展名则填默认值application/octet-stream
            metadata.setContentType(getContentType(path));
            // 指定该Object被下载时的名称（指示MINME用户代理如何显示附加的文件，打开或下载，及文件名称）
            metadata.setContentDisposition("attachment;fileName=" + fileName);
            // 上传文件 (上传文件流的形式)

            ApplicationContextProvider.getBean(RootCommonUtils.class).ansyUploadToOss(ossClient, bucketName, metadata,
                path, fileName, is);

            // url=getUrl(bucketImageName, path);
            // 解析结果
            // PutObjectResult putResult = ossClient.putObject(bucketName, path, is, metadata);
            // String resultStr = putResult.getETag();

            // url=getUrl(bucketImageName, path);
            url = path;
        } catch (Exception e) {
            throw new Exception("upload file error");
        }
        return url;
    }

    /**
     * 上传文件到OSS
     *
     * @param path
     * @param fileName
     * @param is
     * @return
     */
    public static String uploadObject2Oss(String path, String fileName, InputStream is) throws Exception {
        OSSClient ossClient = getOssClient();

        String url = null;
        try {

            if (ossClient.doesBucketExist(bucketName)) {
                // logger.error("您已经创建Bucket：" + bucketName + "。");
            } else {
                // 创建Bucket。
                ossClient.createBucket(bucketName);
            }

            // 创建上传Object的Metadata
            ObjectMetadata metadata = new ObjectMetadata();
            // 上传的文件的长度
            metadata.setContentLength(is.available());
            // 指定该Object被下载时的网页的缓存行为
            metadata.setCacheControl("no-cache");
            // 指定该Object下设置Header
            metadata.setHeader("Pragma", "no-cache");
            // 指定该Object被下载时的内容编码格式
            metadata.setContentEncoding("utf-8");
            // 文件的MIME，定义文件的类型及网页编码，决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成，
            // 如果没有扩展名则填默认值application/octet-stream
            metadata.setContentType(getContentType(fileName));
            // 指定该Object被下载时的名称（指示MINME用户代理如何显示附加的文件，打开或下载，及文件名称）
            metadata.setContentDisposition("attachment;fileName=" + java.net.URLEncoder.encode(fileName, "UTF-8"));
            // 上传文件 (上传文件流的形式)

            // ApplicationContextProvider.getBean(RootCommonUtils.class).ansyUploadToOss(ossClient, bucketName,
            // metadata,
            // path, fileName, is);
            ossClient.putObject(bucketName, path, is, metadata);
            ossClient.shutdown();
            // url=getUrl(bucketImageName, path);
            // 解析结果
            // PutObjectResult putResult = ossClient.putObject(bucketName, path, is, metadata);
            // String resultStr = putResult.getETag();

            // url=getUrl(bucketImageName, path);
            url = path;
        } catch (Exception e) {
            log.sysErrLog("uploadObject2Oss", "uploadObject2Oss error", e);
            throw new Exception("upload file error", e);
        }
        return url;
    }

    /**
     * 获得url链接
     *
     * @param key
     * @return
     */
    public static String getUrl(String key, int day) {

        OSSClient ossClient = getOssClient();
        // 设置URL过期时间为100年 3600l* 1000*24*365*10
        Date expiration = null;
        if (day <= 0) {
            expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 100);
        } else {
            expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * day);
        }
        // 生成URL
        URL url = ossClient.generatePresignedUrl(bucketName, key, expiration);
        ossClient.shutdown();
        if (url != null) {
            return url.toString();
        }
        return null;
    }

    /**
     * 通过文件名判断并获取OSS服务文件上传时文件的contentType
     *
     * @param fileName
     *            文件名
     * @return 文件的contentType
     */
    public static String getContentType(String fileName) {
        // 文件的后缀名
        String fileExtension = "";
        if (fileName.contains(".")) {
            fileExtension = fileName.substring(fileName.lastIndexOf("."));
        }
        if (".bmp".equalsIgnoreCase(fileExtension)) {
            return "image/bmp";
        }
        if (".gif".equalsIgnoreCase(fileExtension)) {
            return "image/gif";
        }
        if (".jpeg".equalsIgnoreCase(fileExtension) || ".jpg".equalsIgnoreCase(fileExtension)
            || ".png".equalsIgnoreCase(fileExtension)) {
            return "image/jpeg";
        }
        if (".png".equalsIgnoreCase(fileExtension)) {
            return "mage/png";
        }
        if (".html".equalsIgnoreCase(fileExtension)) {
            return "text/html";
        }
        if (".txt".equalsIgnoreCase(fileExtension)) {
            return "text/plain";
        }
        if (".vsd".equalsIgnoreCase(fileExtension)) {
            return "application/vnd.visio";
        }
        if (".ppt".equalsIgnoreCase(fileExtension) || "pptx".equalsIgnoreCase(fileExtension)) {
            return "application/vnd.ms-powerpoint";
        }
        if (".doc".equalsIgnoreCase(fileExtension) || "docx".equalsIgnoreCase(fileExtension)) {
            return "application/msword";
        }
        if (".xml".equalsIgnoreCase(fileExtension)) {
            return "text/xml";
        }
        if (".xls".equalsIgnoreCase(fileExtension) || "xlsx".equalsIgnoreCase(fileExtension)) {
            return "application/vnd.ms-excel";
        }
        if (".mp3".equalsIgnoreCase(fileExtension) || "mp3".equalsIgnoreCase(fileExtension)) {
            return "audio/mp3";
        }
        // 默认返回类型
        return "application/octet-stream";
    }

    public static String uploadObject2Oss1(String path, String fileName, InputStream is) throws Exception {
        OSSClient ossClient = getOssClient1();
        String bucketName = "zkkj";
        String url = null;
        try {

            if (ossClient.doesBucketExist(bucketName)) {
                // logger.error("您已经创建Bucket：" + bucketName + "。");
            } else {
                // 创建Bucket。
                ossClient.createBucket(bucketName);
            }

            // 创建上传Object的Metadata
            ObjectMetadata metadata = new ObjectMetadata();
            // 上传的文件的长度
            metadata.setContentLength(is.available());
            // 指定该Object被下载时的网页的缓存行为
            metadata.setCacheControl("no-cache");
            // 指定该Object下设置Header
            metadata.setHeader("Pragma", "no-cache");
            // 指定该Object被下载时的内容编码格式
            metadata.setContentEncoding("utf-8");
            // 文件的MIME，定义文件的类型及网页编码，决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成，
            // 如果没有扩展名则填默认值application/octet-stream
            metadata.setContentType(getContentType(fileName));
            // 指定该Object被下载时的名称（指示MINME用户代理如何显示附加的文件，打开或下载，及文件名称）
            metadata.setContentDisposition("attachment;fileName=" + fileName);
            // 上传文件 (上传文件流的形式)
            ossClient.putObject(bucketName, path, is, metadata);
            // url=getUrl(bucketImageName, path);
            // 解析结果
            // PutObjectResult putResult = ossClient.putObject(bucketName, path, is, metadata);
            // String resultStr = putResult.getETag();

            // url=getUrl(bucketImageName, path);
            url = path;
            ossClient.shutdown();
        } catch (Exception e) {
            throw new Exception("upload file error");
        }
        return url;
    }

    public static OSSClient getOssClient1() {
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";
        String accessKeyId = "LTAI4FfYJajBdpPQUgB1YRTf";
        String accessKeySecret = "AC5ASX89oyhgha2hqQYLTBS4NcFX8P";
        return new OSSClient(endpoint, accessKeyId, accessKeySecret);
    }

    public static String getUrl1(String key, int day) {
        OSSClient ossClient = getOssClient1();
        String bucketName = "zkkj";
        // 设置URL过期时间为100年 3600l* 1000*24*365*10
        Date expiration = null;
        if (day <= 0) {
            expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 100);
        } else {
            expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * day);
        }
        // 生成URL
        URL url = ossClient.generatePresignedUrl(bucketName, key, expiration);
        ossClient.shutdown();
        if (url != null) {
            return url.toString();
        }
        return null;
    }
}
